package org.foreveross.que.web.action.help;

import java.net.InetAddress;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.foreveross.que.infra.base.constant.SysConstants;
import org.foreveross.que.secret.SecretDecrypt;
import org.openkoala.koala.auth.ss3adapter.CustomUserDetails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AuthenticationProcessingFilter;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.util.TextEscapeUtils;
import org.springframework.stereotype.Controller;

import org.foreveross.que.application.FbUserApplication;
import org.foreveross.que.application.RoleMenuRApplication;
import org.foreveross.que.application.SystemApplication;
import org.foreveross.que.application.TopicApplication;
import org.foreveross.que.application.TreeMenuApplication;
import org.foreveross.que.entity.MenuEntity;
import org.foreveross.que.entity.SystemEntity;
import org.foreveross.que.vo.IndexVo;
import org.foreveross.que.vo.TreeChildVo;
import org.foreveross.que.web.action.ImportImgBaseAction;

@SuppressWarnings({ "serial","unchecked", "deprecation" })
@Controller
@org.springframework.context.annotation.Scope("prototype")
@Namespace("/help/topic")
@ParentPackage("json-default")
public class FeedbackIndexAction extends ImportImgBaseAction {

	IndexVo vo = new IndexVo();
	@Autowired
	TopicApplication topicApplication;
	@Autowired
	TreeMenuApplication menuApplication;
	@Autowired
	FbUserApplication userApplication;
	@Autowired
	AuthenticationManager authenticationManager;
	@Autowired
	RoleMenuRApplication roleMenuRApplication;
	@Autowired
	SystemApplication systemApplication;

	/**
	 * json 页面登录
	 * 
	 * @return
	 */
	@Action(value = "login", results = { @Result(name = "JSON", type = "json", params = {
			"root", "vo.msg" }) })
	public String login() {
		try {
			if (StringUtils.isEmpty(StringUtils.trimToEmpty(vo.getUsername()))) {
				vo.setMsg("账号不能为空");
			}else if (StringUtils.isEmpty(StringUtils.trimToEmpty(vo.getPassword()))) {
				vo.setMsg("密码不能为空");
			}else{
				SystemEntity sysEntity = this.systemApplication.getEntity(vo
						.getSysType());
				if (sysEntity == null) {
					vo.setMsg("vo.sysType 错误");
					// this.getRequest().setAttribute("errorMsg", "vo.sysType 错误");
				} else {
					this.getSession().setAttribute(SysConstants.SYS_ENTITY,
							sysEntity);
				}
				this.login(vo.getPassword());
				vo.setMsg("1");
			}
		} catch (AuthenticationException ae) {
			vo.setMsg("登录账号或者密码错误！");
			// this.getRequest().setAttribute("errorMsg", "登录账号或者密码错误！");
		}
		return "JSON";
	}
	@Action(value = "loginOut", results = { @Result(name = "JSON", type = "json", params = {
			"root", "vo.msg" }) })
	public String loginOut(){
		this.getSession().removeAttribute(SysConstants.SYS_ENTITY);
		vo.setAuthority(IndexVo.ORDER_ROLE);//无角色是游客
		getSession().removeAttribute(AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY);
		getSession().removeAttribute("SPRING_SECURITY_CONTEXT");
		getSession().removeAttribute(SysConstants.AVAIL_MENUS);
		 vo.setMsg("1");
		 return "JSON";
	}
	
	@Action(value = "tempIndex", results = {
			@Result(name = "dispatcher", type = "dispatcher", location = "/pages/help/auto_forword_index.jsp")})
	public String autoForwordIndex() throws Exception {
		String key = this.getRequest().getParameter("key");
		if(StringUtils.isNotBlank(key)){
			this.getRequest().setAttribute("key",key );
		}
		return "dispatcher";
	}

	/**
	 * 跳转到问题反馈前台页面，如果有口令，解密口令登录
	 * @return
	 * @throws Exception
	 */
	@Action(value = "index", results = {
			@Result(name = "dispatcher", type = "dispatcher", location = "/pages/help/index.jsp"),
			@Result(name = "error", location = "/pages/errors/biz_error.jsp") })
	public String index() throws Exception {
		HttpServletRequest req = this.getRequest();
		System.out.println("----------------------测试ip隐匿性 start---------------------------");
		System.out.println("x-forwarded-for:"+req.getHeader("x-forwarded-for"));
		System.out.println("PRoxy-Client-IP:"+req.getHeader("PRoxy-Client-IP"));
		System.out.println("WL-Proxy-Client-IP:"+req.getHeader("WL-Proxy-Client-IP"));
		System.out.println("req.getRemoteAddr():"+req.getRemoteAddr());
		
		InetAddress host = InetAddress.getLocalHost();
		if(host!=null){
			System.out.println("host.getHostAddress():"+host.getHostAddress());
		}
		System.out.println("--------------------测试ip隐匿性 end-----------------------------");
		try {
			String key = this.getRequest().getParameter("key");
			
			SystemEntity sysEntity = this.systemApplication.getEntity(vo
					.getSysType());
			if (sysEntity == null) {
				this.getRequest().setAttribute("errorMsg", "vo.sysType 错误");
				return "error";
			} else {
				this.getSession().setAttribute(SysConstants.SYS_ENTITY,
						sysEntity);
			}
			if (StringUtils.isNotBlank(key)) {
				try {
					String paramsStr = SecretDecrypt.decrypt(
							sysEntity.getSecretKey(), key);
					if (!loadVoByKey(paramsStr)) {
						return "error";
					} else {
						autoLogin();
						autoAddMenu();
					}
				} catch (Exception e) {
					e.printStackTrace();
					this.getRequest().setAttribute("errorMsg",
							"key is invalid!!");
					return "error";
				}
			} else {
				vo.setUsername(null);
			}
		} catch (AuthenticationException ae) {
			// throw new AccessDeniedException("wrong username or password !");
			this.getRequest(). 	setAttribute("errorMsg", "login fail!!");
			return "error";
		}
		loadAuthority(vo);
		return "dispatcher";
	}


/**
 * 自动登录
 * @throws Exception
 */
	private void autoLogin() throws Exception{
		CustomUserDetails loginUser = this.getLoginUser();
		String userAccount = vo.getUsername();
		if (StringUtils.isNotBlank(userAccount)) {
			if (loginUser == null
					|| !StringUtils.equals(
							loginUser.getUsername(),
							userAccount)) {
				// 保存或者更新用户
				this.userApplication.saveUser(userAccount,
						vo.getSysType());
				login("");//自动登录
			}
			
		}
		
		
	}
/**
 * 如果不存在code，自动新增	
 * @throws Exception
 */
	private void autoAddMenu() throws Exception{
		if(StringUtils.isNotBlank(vo.getMenu().getCode())){
			if(StringUtils.isEmpty(StringUtils.trimToNull(vo.getMenu().getName()))){
				//新增的节奏，讨论区名不能为空，不带讨论区code直接跳转吧
				return ;
			}
		TreeChildVo node = menuApplication.getTreeById(vo.getMid(), vo.getSysType());
			if(node==null){
				//自动新增讨论区
				menuApplication.addMenu(vo);
			}
		}
	}

	/**
	 * 解密口令成参数，装载进action vo里面
	 * 
	 * @param paramsStr
	 *            口令
	 * @return
	 */
	private boolean loadVoByKey(String paramsStr) {
		Long requestTime = 0L;
		Long availTime = 0L;
		try {
			String[] arr = StringUtils.split(paramsStr, "&");

			for (String param : arr) {
				String[] kv = StringUtils.split(param, "=");
				MenuEntity menu = vo.getMenu();
				if ("mid".equals(kv[0])) {
					vo.setMid(kv[1]);
					menu.setCode(kv[1]);
				} else if ("username".equals(kv[0])) {
					vo.setUsername(kv[1]);
				} else if ("requestTime".equals(kv[0])) {
					requestTime = Long.parseLong(kv[1]);
				} else if ("availTime".equals(kv[0])) {
					availTime = Long.parseLong(kv[1]);
				} else if ("pid".equals(kv[0])) {
					menu.setPid(kv[1]);
				} else if ("discussName".equals(kv[0])) {
					menu.setName(kv[1]);
				} 
			}
		} catch (Exception e) {
			this.getRequest().setAttribute("errorMsg", "参数设置错误。");
			return false;
		}
		if (StringUtils.isBlank(vo.getUsername())) {
			this.getRequest().setAttribute("errorMsg", " username 未设置");
			return false;
		}
		if (System.currentTimeMillis() - requestTime > availTime) {
			this.getRequest().setAttribute("errorMsg", "口令已过时，请重新登录。");
			return false;
		}
		return true;
	}

	/**
	 * 检索（按某些条件）
	 * 
	 * @return
	 */
	@Action(value = "search", results = { @Result(name = "JSON", type = "json", params = {
			"root", "vo.pageData" }) })
	public String search() throws Exception {
		vo.setLoginUser(super.getLoginUser());
		List<String> availMenus = (List<String>) getRequest().getSession()
				.getAttribute(SysConstants.AVAIL_MENUS);
		// if(availMenus!=null){
		topicApplication.loadTopics(vo, availMenus);
		// }else{
		// vo.getPageData().setState(SysConstants.ZERO_INT);
		// }
		return "JSON";
	}

	/**
	 * json获取功能树
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "menus", results = { @Result(name = "JSON", type = "json", params = {
			"root", "vo.menus" }) })
	public String getMenus() throws Exception {
		// List<String> availMenus = (List<String>
		// )getRequest().getSession().getAttribute(SysConstants.AVAIL_MENUS);
		// if(availMenus==null){//角色功能权限
		// availMenus =
		// roleMenuRApplication.getRoleMenus(this.getRoles().keySet(),
		// vo.getSysType());
		// getRequest().getSession().setAttribute(SysConstants.AVAIL_MENUS,
		// availMenus);
		// }
		// if(availMenus!=null){

		// List<TreeChildVo> menus =
		// menuApplication.getTreeByRoleMList(availMenus, vo.getSysType());
		List<TreeChildVo> menus = menuApplication.getMenuTree(vo.getSysType());
		vo.setMenus(menus);
		// }
		return "JSON";
	}

	/**
	 * json发起一个讨论话题
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "launchTopic", results = { @Result(name = "JSON", type = "json", params = {
			"root", "vo.msg" }) })
	public String launchTopic() throws Exception {
		this.loadAuthority(vo);
//		if ("0".equals(vo.getAuthority())) {
//			vo.setMsg("页面过期，请重新从系统进入页面");
//		} else {
			String content = super.contentDecrypt(vo.getTopicVo()
					.getSubjectInfo());
			vo.getTopicVo().setSubjectInfo(content);
			vo.getTopicVo().setCreateUrole(vo.getRoleid());
			if (this.topicApplication.launchTopic(vo) != null) {
				vo.setMsg("提交问题成功");
			}
//		}
		return "JSON";
	}

	/**
	 * json查找讨论区描述
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "findMenuDesc", results = { @Result(name = "JSON", type = "json", params = {
			"root", "vo.menuDesc" }) })
	public String findMenuDesc() throws Exception {
		MenuEntity entity = this.menuApplication.findEntity(vo.getMid());
		vo.setMenuDesc(entity.getDescription());
		return "JSON";
	}

	/**
	 * 
	 * json更新讨论区描述
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "updateMenuDesc", results = { @Result(name = "JSON", type = "json", params = {
			"root", "vo.menuDesc" }) })
	public String updateMenuDesc() throws Exception {
		loadAuthority(vo);
		if (IndexVo.ORDER_ROLE.equals(vo.getAuthority())) {// 判断角色权限
			vo.setMenuDesc("页面过期，请重新从系统进入页面");
		} else if (IndexVo.CUSTOMER_SERVICE_ROLE.equals(vo.getAuthority())) {
			String desc = super.contentDecrypt(vo.getMenuDesc());
			vo.setMenuDesc(desc);
			this.menuApplication.updateMenuDesc(vo);// 只要不抛错就算成功,该方法自动装置成功信息
		}
		return "JSON";
	}

	/**
	 * json取消或者置顶话题
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "isStickie", results = { @Result(name = "JSON", type = "json", params = {
			"root", "vo.msg" }) })
	public String isStickie() throws Exception {
		loadAuthority(vo);
		if (IndexVo.ORDER_ROLE.equals(vo.getAuthority())) {// 判断角色权限
			vo.setMenuDesc("页面过期，请重新从系统进入页面");
		} else if (IndexVo.CUSTOMER_SERVICE_ROLE.equals(vo.getAuthority())) {
			this.topicApplication.updateIsStickie(vo.getTopicVo().getId(), vo
					.getTopicVo().getIsStickie());
			vo.setMsg("操作成功");
		}
		return "JSON";
	}

	/**
	 * json查找一个讨论话题
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "findTopic", results = { @Result(name = "JSON", type = "json", params = {
			"root", "vo.topicVo" }) })
	public String findTopic() throws Exception {
//		List<String> availMenus = (List<String>) getRequest().getSession()
//				.getAttribute(SysConstants.AVAIL_MENUS);
		this.topicApplication.loadTopic(vo);
		return "JSON";
	}
	/**
	 * 如果参数password不为空 ，vo里面的用户名根据密码登录，如果password为空，默认密码登录
	 * 该方法仅用于逻辑处理。
	 * @param password
	 */
	private void login(String password) {
		String userAccount = vo.getUsername();

		if (StringUtils.isBlank(password)) {
			password = SysConstants.PASSWORD_KEY;
		}
		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
				userAccount, password);
		AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
		authRequest.setDetails(authenticationDetailsSource.buildDetails(this
				.getRequest()));

		SecurityContext securityContext = SecurityContextHolder.getContext();
		Authentication authentication = authenticationManager
				.authenticate(authRequest);
		getSession()
				.setAttribute(
						AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY,
						TextEscapeUtils.escapeEntities(userAccount));
		securityContext.setAuthentication(authentication);
		SecurityContextHolder.setContext(securityContext);
		this.getSession().setAttribute("SPRING_SECURITY_CONTEXT",
				securityContext);
		List<String> availMenus = (List<String>) getRequest().getSession()
				.getAttribute(SysConstants.AVAIL_MENUS);

		availMenus = roleMenuRApplication.getRoleMenus(
				this.getRoles().keySet(), vo.getSysType());
		getRequest().getSession().setAttribute(SysConstants.AVAIL_MENUS,
				availMenus);
	}

	public IndexVo getVo() {
		return vo;
	}

	public void setVo(IndexVo vo) {
		this.vo = vo;
	}

}
